﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web;

namespace U01_boke
{
    /// <summary>
    /// APIHandler
    /// </summary>
    public class APIHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {

            SysApi sysApi = GetMethod(context);

            //获取请求参数
            string json = context.Request.QueryString["param"] ?? context.Request.Form["param"];

            Type type = typeof(Api);
            MethodInfo method = type.GetMethod(sysApi.Api_Method, BindingFlags.Public | BindingFlags.Instance);

            //获取方法参数
            object[] objs = AnalysisFuncParame(json, method);

            //执行函数
            object method_result = method?.Invoke(Activator.CreateInstance(type), objs);

            context.Response.Write(NewtonsoftFactory.Serialize(method_result));
            context.Response.End();
        }

        /// <summary>
        /// 根据接口参数查询出对应的方法
        /// </summary>
        private SysApi GetMethod(HttpContext context)
        {
            //获取接口名称参数
            string api_code = context.Request.QueryString["method"];
            if (string.IsNullOrEmpty(api_code))
                throw new ResultException("low B！Can you use it?", (int)HttpStatusCode.NoParam);
            //查询API
            var (ip_sql, param) = SQLBuilder.API_Single_SQL(api_code);
            SysApi sysApi = SqlHelper.ExecuteDataReader<SysApi>(ip_sql, param);
            if (sysApi == null && sysApi.IsDisabled != 0)
                throw new ResultException("no api!", (int)HttpStatusCode.NoParam);
            string http_method_name = ((HttpMethodCode)sysApi.Api_Http_Method).ToString();
            if (!context.Request.HttpMethod.Equals(http_method_name))
                throw new ResultException($"该接口不支持{context.Request.HttpMethod}请求!", (int)HttpStatusCode.HttpMethod);

            return sysApi;
        }

        /// <summary>
        /// 根据JSON字符串，解析成函数参数
        /// </summary>
        /// <param name="json">字符串</param>
        /// <param name="method">函数</param>
        private object[] AnalysisFuncParame(string json, MethodInfo method)
        {
            //获取函数所有参数信息
            var param = method.GetParameters();
            //参数数据容器
            object[] objs = new object[param.Length];
            if (param.Length == 0)
                return null;
            //解析json字符串
            var nameValue = SerializerFactory.Deserialize<Dictionary<string, object>>(json);

            for (int i = 0; i < param.Length; i++)
            {
                var p = param[i];
                //1：获取方法参数的类型
                var parameterType = p.ParameterType;

                //2：创建默认值
                var defaultValue = parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null;

                //3：先将默认值保存到容器中，后面如果出现转换失败就直接使用默认值
                objs[i] = (p.HasDefaultValue ? p.DefaultValue : defaultValue);

                //4：验证json中是否包含参数Key，没有则跳过此次循环
                if (nameValue == null || !nameValue.ContainsKey(p.Name)) continue;

                //5：根据参数名称取出json中对应的value值
                var value = nameValue[p.Name];

                //6：参数类型如果和json解析出的类型一致，则不需要转换
                if (parameterType.FullName.Equals(value.GetType().FullName))
                {
                    objs[i] = value;
                    continue;
                }

                //7:进行转换操作
                //如果是数组或者泛型，使用序列化转换,
                if (parameterType.IsArray || parameterType.IsGenericType)
                    value = SerializerFactory.ConvertToType(value, parameterType);
                else
                    value = Convert.ChangeType(value, parameterType);
                objs[i] = value;
            }
            return objs;
        }

        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
}